#include "base/log.hpp"

#include "base/log_util.hpp"
#include "errno.h"

#include <unordered_map>

namespace ibox::base {
constexpr const char *to_string(LogLevel level) {
    switch (level) {
        case LogLevel::Debug:
            return "DEBUG";
        case LogLevel::Info:
            return "INFO";
        case LogLevel::Warning:
            return "WARNING";
        case LogLevel::Error:
            return "ERROR";
        case LogLevel::Fatal:
            return "FATAL";
        default:
            return "";
    }
}

void Log::log_formatter(context const &ctx, buffer_t &buffer) {
    // prepare data
    const auto *level_text = to_string(ctx.level);
    const auto *func_name = ctx.func_name;
    const auto *filename = ctx.short_filename;
    // log name
    // if (ctx.log_name) {
    //    fmt::format_to(fmt::appender(buffer), "[{}]", ctx.log_name);
    //}

    // log date
    fmt::format_to(fmt::appender(buffer), "[{}]", get_current_datetime());
    // log level
    fmt::format_to(fmt::appender(buffer), "[{:<7}]", level_text);

    fmt::format_to(fmt::appender(buffer), "[tid:{:d}]", ctx.tid);
    if (filename) {
        fmt::format_to(fmt::appender(buffer),
                       "[{}:{:d}]",
                       filename,
                       ctx.line); // log file-line
    }
    // log func_name
    if (func_name) {
        fmt::format_to(fmt::appender(buffer),
                       "[func:{}]",
                       func_name); // log file-line
    }

    fmt::string_view text{ctx.text.data(), ctx.text.size()};

    fmt::format_to(fmt::appender(buffer), ": {}",
                   text); // log info

    // 最后添加回车换行
    buffer.push_back('\n');
}

std::unordered_map<LogLevel, fmt::color> levels_colors = {
    {LogLevel::Debug, fmt::color::navajo_white},
    {LogLevel::Info, fmt::color::spring_green},
    {LogLevel::Warning, fmt::color::orange},
    {LogLevel::Error, fmt::color::red},
    {LogLevel::Fatal, fmt::color::dark_red},
};

fmt::color get_color_by_level(LogLevel level) { return levels_colors[level]; }

void Log::colorful_formatter(context const &ctx, buffer_t &buffer) {
    // prepare data
    const auto *level_text = to_string(ctx.level);
    const auto *func_name = ctx.func_name;
    const auto *filename = ctx.long_filename;

    // log date
    fmt::format_to(std::back_inserter(buffer), "[{}]", get_current_datetime());
    // log level
    fmt::format_to(std::back_inserter(buffer),
                   fg(get_color_by_level(ctx.level)),
                   "[{:<7}]",
                   level_text);
    fmt::format_to(std::back_inserter(buffer), "[tid:{:d}]", ctx.tid);
    // log file-line
    if (filename) {
        fmt::format_to(
            std::back_inserter(buffer), "[{}:{:d}]", filename, ctx.line);
    }
    // log func_name
    if (func_name) {
        fmt::format_to(std::back_inserter(buffer), "[func:{}]", func_name);
    }
    fmt::string_view text{ctx.text.data(), ctx.text.size()};
    if (ctx.level >= LogLevel::Error
        && errno < 0) { // if level >= Error,get the error info
        fmt::format_to(std::back_inserter(buffer),
                       fg(get_color_by_level(ctx.level)),
                       ": {} ^system error:{}",
                       text,
                       get_error_info(errno)); // 打印系统错误提示信息
    } else {
        fmt::format_to(std::back_inserter(buffer),
                       fg(get_color_by_level(ctx.level)),
                       ": {}",
                       text); // log info
    }
    // 最后添加回车换行
    buffer.push_back('\n');
}

} // namespace ibox::base
